#pragma once

#include <iostream>
#include <string>
#include <memory>
#include <sys/select.h>
#include <poll.h>
#include "Log.hpp"
#include "Socket.hpp"
#include <cerrno>
#include <functional>

using namespace LogMudule;

#define MAX 1024

const int gdefaultfd = -1;

using handle_t = std::function<std::string(const std::string)>;

class PollServer
{

public:
    PollServer(int port, handle_t handle)
        : _port(port),
          _sock(std::make_shared<TcpSocket>(gdefaultfd)),
          _handle(handle)
    {
    }

    // 初始化
    void Init()
    {
        // 初始化套接字
        _sock->BuildTcpSocketMethod(_port);

        // 初始化辅组数组
        for (int i = 0; i < MAX; ++i)
        {
            _poll_array[i].fd = gdefaultfd;
            _poll_array[i].events = 0;
            _poll_array[i].revents = 0;
        }

        // 将监听套接字加入辅组数组
        _poll_array[0].fd = _sock->Fd();
        _poll_array[0].events |= POLL_IN;
    }

    void Start()
    {
        while (true)
        {
            // 设置超时时间
            int timeout = -1;

            // 开始等待
            int n = poll(_poll_array, MAX, timeout);
            if (n > 0) // 有就绪的文件描述符
            {
                LOG(LogLevel::DEBUG) << "有就绪的文件描述符";
                DisposeFd();
            }
            else if (n == 0) // 没有就绪的文件描述符
            {
                LOG(LogLevel::DEBUG) << "时间到了，没有就绪的文件描述符";
                continue;
            }
            else
            {
                LOG(LogLevel::ERROR) << "poll error :" << errno;
                return;
            }
        }
    }

    void DisposeFd()
    {
        for (int i = 0; i < MAX; ++i)
        {
            if (_poll_array[i].fd == gdefaultfd)
            {
                continue;
            }

            // 是监听文件描述符
            if (_poll_array[i].fd == _sock->Fd())
            {
                // 有新连接到来
                if (_poll_array[i].revents & POLL_IN)
                {
                    // 处理连接
                    Accept();
                }
            }
            else if (_poll_array[i].revents & POLL_IN) // 通信文件描述符
            {
                // 处理信息
                RS(i);
            }
        }
    }

    void Accept()
    {

        InetAddr client;
        std::shared_ptr<Socket> sk = _sock->Accepter(&client);

        // 添加套接字进辅组数组
        int index = -1;
        for (int i = 0; i < MAX; ++i)
        {
            if (_poll_array[i].fd == gdefaultfd)
            {
                index = i;
                break;
            }
        }

        // 能够管理的fd满了
        if (index == -1)
        {
            // 这里可以对_poll_array进行扩容
            //....

            sk->Close();
            return;
        }

        // 设置进行辅组数组
        _poll_array[index].fd = sk->Fd();
        _poll_array[index].events |= POLL_IN;
    }

    void RS(int index)
    {
        std::string out;
        char buffer[1024];
        int n = read(_poll_array[index].fd, buffer, sizeof(buffer) - 1);
        if (n > 0) // 读到数据
        {
            buffer[n] = 0;
            out = buffer;
            LOG(LogLevel::DEBUG) << "buffer: " << out;

            std::string res = _handle(out);

            LOG(LogLevel::DEBUG) << "准备发送： " << _poll_array[index].fd;
            int n = send(_poll_array[index].fd, res.c_str(), res.size(), 0);
            if (n < 0)
            {
                LOG(LogLevel::ERROR) << "send err...";
            }
            LOG(LogLevel::DEBUG) << "send succeed...";
        }
        else if (n == 0) // 对端关闭
        {
            // 关闭fd
            close(_poll_array[index].fd);

            // 从辅组数组中移出
            _poll_array[index].fd = gdefaultfd;
            _poll_array[index].events = 0;

            LOG(LogLevel::DEBUG)<< "对端退出";
        }
        else
        {
            LOG(LogLevel::ERROR) << "read err...";
            return;
        }
    }

    ~PollServer()
    {
        for (int i = 0; i < MAX; ++i)
        {
            if (_poll_array[i].fd != gdefaultfd)
            {
                close(_poll_array[i].fd);
            }
        }
    }

private:
    uint16_t _port;                             // 端口号
    std::shared_ptr<Socket> _sock;              // socket

    struct pollfd _poll_array[MAX]; // 辅组数组
    handle_t _handle;   //回调函数
};